package com.airlines.crewassignment.domain.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Duration;

import com.airlines.common.DateTimeRangeUtil;
import com.airlines.common.StringToListUtil;
import com.airlines.crewassignment.constant.RuleConstant;
import com.airlines.crewassignment.domain.Crew;
import com.airlines.crewassignment.domain.CrewPositionAssignment;
import com.airlines.crewassignment.domain.CrewTask;
import com.airlines.crewassignment.domain.DateTimeRange;
import com.airlines.crewassignment.domain.FlightInfo;
import com.airlines.crewassignment.domain.LinkLine;

/**
 * @author xxxx
 * @date 2018年5月8日 
 * @description 告警类规则计算
 */

public class WaringRuleUtil {
	/**
	 * 查询同一个连线中，一个机组成员与其他机组成员是否有冲突
	 * 冲突，返回true
	 * 不冲突，返回false
	 * @param list
	 * @param crew
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static boolean hasCrewConflict(List<CrewPositionAssignment> list,Crew crew){
		//1.获取所有的同一连线的其他人员
		if(crew.getCrewConflictOther() == null){
			return false;
		}
		List<String> otherCrewWorkcode = new ArrayList<>();
		for(CrewPositionAssignment cpa : list){
			String otherWorkcode = cpa.getCrew().getWorkcode();
			if(!StringUtils.equals(crew.getWorkcode(), otherWorkcode)){
				otherCrewWorkcode.add(otherWorkcode);
			}
			
		}

		//2.获取同一个航班上的其他人人员，包括飞行、乘务、保卫
		for(CrewPositionAssignment cpa : list){
			for(FlightInfo f : cpa.getPosition().getLinkLine().getFlightInfoList()){
				for(String workcode :StringToListUtil.getList(f.getCrewWorkcodesAll(), ",")){
					if(!StringUtils.equals(workcode, crew.getWorkcode())){
						otherCrewWorkcode.add(workcode);
					}
				}
			}
			
			
		}
		
		
		//本机组人员的冲突人员，与本连线人员没有交集，则没有冲突，有交集，则冲突
		List<String> conflictWorkcodeList = crew.getCrewConflictOther().getConflictWorkcodeList();
		if(CollectionUtils.isEmpty(otherCrewWorkcode) || CollectionUtils.isEmpty(conflictWorkcodeList)){
			return false; // 没有冲突
		}
		Collection<String> intersection  = CollectionUtils.intersection(otherCrewWorkcode, conflictWorkcodeList);
		if(CollectionUtils.isEmpty(intersection)){
			return false;
		}else{
			return true;
		}
	}
	
	/**
	 * 检查该安排的号位，是否与不在位信息冲突
	 * 冲突，返回true
	 * 不冲突 ，返回false
	 * @param crewPositionAssignment
	 * @return
	 */
	public static boolean crewTaskConflict(CrewPositionAssignment crewPositionAssignment){
		
		List<CrewTask> crewTaskList = crewPositionAssignment.getCrew()
				.getCrewFlightExperience()
				.getCrewTaskListBetweenFlightDate();
		if(CollectionUtils.isEmpty(crewTaskList)){
			//如果在自动排班时间范围内没有不在位信息，则排班必定不会冲突
			return false;
		}
		
		LinkLine linkLine = crewPositionAssignment.getPosition().getLinkLine();
		DateTimeRange linkLineRange = new DateTimeRange(linkLine.getTd(),linkLine.getTa());
		
		
		//如果连线时间与任何一个已经安排的不在位时间冲突，则排班必定冲突
		for(CrewTask crewTast : crewTaskList){
			DateTimeRange taskDateTimeRange = crewTast.getDateTimeRange();
			if(DateTimeRangeUtil.isIntersection(linkLineRange, taskDateTimeRange)){
				return true;
			}
		}
		
		
		return false;
	}
	
	/**
	 * 查询某个飞行员 在某个连线时刻之前的间隔飞行时间,返回分钟
	 * @param crew
	 * @param linkLine
	 * @param crewLinkLineList
	 * @return
	 */
	public static int getLastFlightDiffTime(Crew crew,LinkLine thisLinkLine,List<LinkLine> crewLinkLineList){
		LinkLine lastLinkLine = getLastLinkLine(crew, thisLinkLine, crewLinkLineList);
		if(lastLinkLine == null){
			return 0;
		}else{
			DateTimeRange  dtr = new DateTimeRange(lastLinkLine.getTa(),thisLinkLine.getTd());
			return dtr.getDuration();
		}
	}
	
	/**
	 * 落地时间在20点之后，次日不安排12点前的航班
	 * 检查某一个飞行员的连线，是否符合某一个连线A，他的上一个连线B，如何符合（B在20点之后，A在第二天12点之前 ）这种模式，则返回 ture
	 * @param crew
	 * @param thisLinkLine
	 * @param crewLinkLineList
	 * @return
	 */
	public static boolean w0013Check(Crew crew,LinkLine thisLinkLine,List<LinkLine> crewLinkLineList){
		LinkLine lastLinkLine = getLastLinkLine(crew, thisLinkLine, crewLinkLineList);
		if(lastLinkLine ==null){
			return false;
		}
		DateTime lastFlightDate = new DateTime(lastLinkLine.getFlightDate()).withTimeAtStartOfDay();
		DateTime lastTa = new DateTime(lastLinkLine.getTa());
		
		DateTime thisFlightDate = new DateTime(thisLinkLine.getFlightDate()).withTimeAtStartOfDay();
		DateTime thisTd = new DateTime(thisLinkLine.getTd());
		
		
		Duration duration = new Duration(lastFlightDate, thisFlightDate);
		//相差一天
		if(duration.getStandardDays() == 1){
			boolean flag = lastTa.isAfter(lastFlightDate.plusHours(RuleConstant.W0013_TA_HORE))
						&& thisTd.isBefore(thisFlightDate.plusHours(RuleConstant.W0013_NEXT_DAY_TD_HORE));
						
			if(flag){
				return true;
			}
		}
		
		
		return false;
	}

	/**
	 * 落地时间在24点之后，次日不安排航班
	 * @param crew
	 * @param thisLinkLine
	 * @param crewLinkLineList
	 * @return 检查某一个飞行员的连线，是否符合某一个连线A，他的上一个连线B，如何符合（B在24点之后，A在第二天24点之前 ）这种模式，则返回 ture
	 */
	public static boolean w0014Check(Crew crew,LinkLine thisLinkLine,List<LinkLine> crewLinkLineList){
		LinkLine lastLinkLine = getLastLinkLine(crew, thisLinkLine, crewLinkLineList);
		if(lastLinkLine ==null){
			return false;
		}
		DateTime lastFlightDate = new DateTime(lastLinkLine.getFlightDate()).withTimeAtStartOfDay();
		DateTime lastTa = new DateTime(lastLinkLine.getTa());
		
		DateTime thisFlightDate = new DateTime(thisLinkLine.getFlightDate()).withTimeAtStartOfDay();
		DateTime thisTd = new DateTime(thisLinkLine.getTd());
		
		
		Duration duration = new Duration(lastFlightDate, thisFlightDate);
		//相差一天
		if(duration.getStandardDays() == 1){
			boolean flag = lastTa.isAfter(lastFlightDate.plusHours(RuleConstant.W0014_TA_HORE))
						&& thisTd.isBefore(thisFlightDate.plusHours(RuleConstant.W0014_NEXT_DAY_TD_HORE));
						
			if(flag){
				return true;
			}
		}
		
		
		return false;
	}
	/**
	 * 从飞行员相关的连线中,获取本连线的上一次连线，包括飞行员在排班前的最后一次连线
	 * @param thisLinkLine
	 * @param crewLinkLineList
	 * @return
	 */
	private static LinkLine getLastLinkLine(Crew crew ,LinkLine thisLinkLine,List<LinkLine> crewLinkLineList){
		if(thisLinkLine == null ){
			return null;
		}
		if(CollectionUtils.isEmpty(crewLinkLineList)){
			return null;
		}
		List<Date> flyTdList = new ArrayList<>();
		List<LinkLine> listAll  = new ArrayList<>();
		LinkLine lastLinkLineBeforeWorkSpace = crew.getCrewFlightExperience().getLastLinkLine();
		if(lastLinkLineBeforeWorkSpace !=null){
			listAll.add(lastLinkLineBeforeWorkSpace);
			listAll.addAll(crewLinkLineList);
		}
		
		for(LinkLine l : listAll){
			flyTdList.add(l.getTd());
		}
		
		Collections.sort(flyTdList);  


		int index = 0;
		for(int i = 0 ; i < flyTdList.size(); i++){
			if(thisLinkLine.getTd().equals(flyTdList.get(i))){
				index = i;
				break;
			}
		}
		
		
		if(index > 0){
			Date lastFlyTd = flyTdList.get(index-1);
			for(LinkLine l : listAll){
				if(l.getTd().equals(lastFlyTd)){
					return l;
				}
			}
		}
		
		return null;		
	}
	
}
